home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Loadstar 224
/
224.d81
/
t.dir to bas
< prev
next >
Wrap
Text File
|
2022-08-26
|
8KB
|
303 lines
u
DIRECTORY TO BASIC
by Dave Moorman
There are two ways to bring a
directory into Basic that I won't use
today. The first is to load up a good
toolbox module such as MR.MOUSE and
use its Directory features. But for
this tutorial, I want to show a
couple of things. So we will
"re-invent" the wheel -- so to speak.
The other method is to OPEN the
directory with an OPEN statement, then
use GET# to bring in the text, one
character at a time. This oft touted
technique has two problems:
1. It is slower than molasses on a
cold morning, and
2. It uses string concatenation, which
I would rather avoid as much as
possible.
As an alternative, I will Bload
the directory into memory. To put the
bytes into a string, I will show a
much faster method.
The program here is designed to go
through a disk directory looking for
files with "L/D." prefixes and Rename
them to have "LD." prefixes. This is
in response to the problem Stephen
Beigle found after using Letter Drop
Writer to create quotes for Letter
Drop. Writer saves files with "L/D."
prefixes, while Letter Drop reads only
files with "LD." prefixes.
So, if you don't want to learn
anything, just run the Run It program.
At the prompt, put a disk full of
Letter Drop Writer quotes (L/D.) in a
drive and choose the drive number from
the menu. In a minute, your files will
all be renamed.
However, if you want to find out
how it is done, stick around!
THE PROGRAM
The first lines are fairly
standard around the Tower.
5 IFPEEK(56)<>64THENPOKE56,64:RUN
This line sets the Top of Basic to
Page 64, giving a lot of free memory
for the Directory.
10 D=PEEK(186):IFD<8THENSTOP
Of course, make D the current
device. On the Run It version, I added
a Menu to allow changing disks.
20 DEFFNH(X)=INT(X/256)
21 DEFFNL(X)=X-FNH(X)*256
These two defined functions will
divide a memory location into two
bytes. There are lots of ways of doing
this. I think it is more elegant to
use FNH(x) and FNL(x) in the body of
the program.
100 REM MAKE A$ A MOVEABLE STRING
101 A$=STR$(PEEK(71)+256*PEEK(72))
102 A=VAL(A$)
Now this bit of code may look odd.
String variables do not directly hold
their string content. They are set up
right along with all other variables,
with two bytes for the variable name
and five bytes for content. Strings
only use three of the five bytes --
for Length, Address Low, and Address
Hi. These two Address bytes point to
the actual contents of the variable.
Back when I used my TRS-80 Model
I, Level II Basic (also by Microsoft),
I found a function called STRPTR(v),
which returned the first byte of the
three-byte pointer for variable v.
Alas, Basic 2.0 does not have STRPTR.
But we do have a very well explored
zero page. And the variable pointers
are pointed to by locations 71/72.
Now the pointer pointer is a very
busy place. Capturing the value there
is tricky, especially for string
variables. So I found a dodge. (I
wanted a Plymouth, but a Dodge will
do!) Look carefully above. The value
in 71/72 is put in a STR$ and put into
A$. That value is the location of the
A$s pointer. I put the VAL(A$) into A,
and now
A holds LENGTH
A+1 holds the LO BYTE
A+2 holds the HI BYTE
The beautiful thing about how a
Microsoft Basic handles string
variable is that when you POKE values
into these three bytes, A$ will
"contain" whatever A bytes start at
A+1/A+2. You can't look under ROM with
this, but any other memory can be very
quickly grabbed into a string
variable.
110 F$="L/D.":F=LEN(F$)+1:REM FIND STR
ING
120 T$="LD.":T=LEN(T$)+1:REM TO STRING
To simplify the code, I put the
FROM prefix in F$ and the TO prefix
into T$, with F and T holding the
length of each (plus 1). As I was
testing, I could easily swap the two
patterns, changing the disk from
"L/D." files to "LD." files and vice
versa.
149 REM BLOAD DIRECTORY
150 SYS57812"$:"+F$+"*",D,0:POKE780,0
:POKE781,0:POKE782,64 :SYS65493
If you don't have this code all
but memorized, you haven't done enough
programming! To Bload a directory in a
format you can read, be sure the
secondary address (the ,0) is 0.
159 REM BEGIN AT 64*256 & SKIP HEADER
160 L=64*256+32
161 L1=2 :REM SKIP 2 BYTES
162 L2=16 :REM LENGTH OF FILENAME
Once the directory is in memory at
Page 64, we need to point to it. Note
-- I [think] in memory pages, which is
why I use 64*256. Who can remember
every page's full memory number?
Also, in this situation, the Header is
not needed, so we add 32 in order to
just skip it.
L1 is set to 2 because the first
two bytes of a directory line hold the
block count as a two-byte integer. We
are going to skip these. However, if
you want to get the block size, use
the following:
DEFFNI(X)=PEEK(X)+256*PEEK(X+1)
BS=FNI(L)
BS will hold the Block Size of the
file.
163 REM CHECK FOR "BLOCK" --END OF DIR
164 POKEA,5:POKEA+1,FNL(L+L1):POKEA+2,
FNH(L+L1):IFA$="BLOCK"THENEND
Any good processing program must
know when to quit. With a directory,
when you get to BLOCKS FREE, you know
you are done. So here we use the
A$-Gambit. We need a 5 byte long
string, beginning with location L+L1.
By POKEing the Length, LOW, and HIGH
into A, A+1, A+2, we make A$ "look" at
the particular directory line.
169 REM FIND FIRST QUOTE MARKS
170 IFPEEK(L+L1)<>34THENL1=L1+1:
GOTO170
175 L1=L1+1
Long ago, in the ancient days of
the PET, someone at Microsoft decided
to save some precious ROM by using the
LIST routine to display the Directory.
It was a clever answer for 1976. Then
CBM built the C-64 in an unprecidented
[TWO MONTHS], and to get the machine
out the door, they just copied Basic
2.0. This is why the Block Size is a
two-byte value rather than the actual
numbers.
When you LIST the Directory, the
Line Number routine generates the
Block Size. But in order to have the
Filenames line up nice and straight,
some Space characters are used to pad
the line before the quote mark. Nice
for them -- a pain for us! In line 170
above, L1 in incremented until a quote
(34) is found, then incremented once
more. L+L1 now points to the beginning
of the filename.
179 REM FIND LENGTH TO 2ND QUOTE MARKS
180 IFPEEK(L+L1+L2)<>34THENL2=L2-1:GOT
o180
Likewise, the filename might be 16
characters long -- or not. So we
decrement L2 to find the end quote
marks.
189 REM POKE LEN, LO, HI INTO A
190 POKEA,L2:POKEA+1,FNL(L+L1):POKEA+2
,FNH(L+L1)
Once we have the Length and
Location of the text, we can POKE the
values into the A$ pointer.
191 REM SCRUB OFF PREFIX
192 A$=MID$(A$,F):PRINTA$
Now, I [could] have just added 5
to L+L1 in line 90. This is more
transparent. We remove the prefix from
A$.
193 REM RENAME TO NEW PREFIX
194 OPEN15,D,15,"R0:"+T$+A$+"="+F$+A$:
CLOSE15
And finally, we can do the Rename.
All that work for just one functional
line! On the otherhand, you could do
all the Renames in Immediate Mode,
like Stephen did.
198 REM ADD 32 TO LOCATION
199 L=L+32:GOTO161
999 end
And lastly, we add 32 to L to
point to the next line, and go to line
161 to do it again.
10000 D=PEEK(186):N$="B.DIR TO BAS":
OPEN1,D,15,"I0":CLOSE1
10001 OPEN1,D,15,"S0:"+N$:CLOSE1:
SAVEN$,D:END
I wanted to show you how I now do
the Scratch and Save routine. The "I0"
is just a safety measure, making sure
the drive is set and ready to work
right. I have had a couple of
"accidents" that could have been
solved by using this one more disk
command.
Well, that's it. I never cease to
be amazed at how ingenius and
club-footed Basic 2.0 is! But since
everything is [always] logical, one
can logically get around any problem!
DMM